using System;
using System.Drawing;
using System.Xml;

namespace PhotoFramePublishingPlugin
{
    // TODO: Use XML serialization with a configuration class for this bit. Can't use Linq-to-XML or XAML, because we're targeting .NET 2.0
    internal static class PersistHelper
    {
        private const int DefaultMaxWidth = 0;
        private const int DefaultMaxHeight = 0;

        private const bool DefaultShouldAddBorders = false;
        private const bool DefaultShouldShortenFileNames = false;

        private const string ParametersXPath = "/Parameters";

        private const string ParametersElementName = "Parameters";
        private const string MaxWidthElementName = "MaxWidth";
        private const string MaxHeightElementName = "MaxHeight";
        private const string DestinationRootElementName = "DestinationRoot";
        private const string ShouldAddBordersElementName = "ShouldAddBorders";
        private const string ShouldShortenFileNamesElementName = "ShouldShortenFilenames";

        public static void InitializeDocument(XmlDocument persistXml)
        {
            persistXml.RemoveAll();
            persistXml.AppendChild(persistXml.CreateProcessingInstruction("xml", "version=\"1.0\""));

            var parametersNode = persistXml.CreateElement(ParametersElementName);
            persistXml.AppendChild(parametersNode);

            parametersNode.AppendChild(persistXml.CreateElement(MaxWidthElementName));
            parametersNode.AppendChild(persistXml.CreateElement(MaxHeightElementName));
            parametersNode.AppendChild(persistXml.CreateElement(DestinationRootElementName));
            parametersNode.AppendChild(persistXml.CreateElement(ShouldAddBordersElementName));
            parametersNode.AppendChild(persistXml.CreateElement(ShouldShortenFileNamesElementName));
        }

        public static Size ReadDimensions(XmlDocument persistXml)
        {
            var parametersNode = persistXml.SelectSingleNode(ParametersXPath);
            if (parametersNode != null)
            {
                var maxWidthNode = parametersNode.SelectSingleNode(MaxWidthElementName);
                var maxHeightNode = parametersNode.SelectSingleNode(MaxHeightElementName);

                if (maxWidthNode != null && maxHeightNode != null)
                {
                    int maxWidth;
                    int maxHeight;

                    if (int.TryParse(maxWidthNode.InnerText, out maxWidth) &&
                        int.TryParse(maxHeightNode.InnerText, out maxHeight))
                    {
                        return new Size(maxWidth, maxHeight);
                    }
                }
            }

            return new Size(DefaultMaxWidth, DefaultMaxHeight);
        }

        public static string ReadDestination(XmlDocument persistXml)
        {
            return ReadString(persistXml, DestinationRootElementName);
        }

        public static bool ReadShouldAddBorders(XmlDocument persistXml)
        {
            return ReadBoolean(persistXml, ShouldAddBordersElementName, DefaultShouldAddBorders);
        }

        public static void WriteDestination(XmlDocument persistXml, string destinationRoot)
        {
            WriteString(persistXml, DestinationRootElementName, destinationRoot);
        }

        public static void WriteDimensions(XmlDocument persistXml, int width, int height)
        {
            var parametersNode = persistXml.SelectSingleNode(ParametersXPath);
            if (parametersNode != null)
            {
                var maxWidthNode = parametersNode.SelectSingleNode(MaxWidthElementName);
                var maxHeightNode = parametersNode.SelectSingleNode(MaxHeightElementName);

                if (maxWidthNode != null && maxHeightNode != null)
                {
                    maxWidthNode.InnerText = Convert.ToString(width);
                    maxHeightNode.InnerText = Convert.ToString(height);
                }
            }
        }

        public static void WriteShouldAddBorders(XmlDocument persistXml, bool shouldAddBorders)
        {
            WriteBoolean(persistXml, ShouldAddBordersElementName, shouldAddBorders);
        }

        public static bool ReadShouldShortenFileNames(XmlDocument persistXml)
        {
            return ReadBoolean(persistXml, ShouldShortenFileNamesElementName, DefaultShouldShortenFileNames);
        }

        public static void WriteShouldShortenFileNames(XmlDocument persistXml, bool value)
        {
            WriteBoolean(persistXml, ShouldShortenFileNamesElementName, value);
        }

        private static void WriteString(XmlDocument persistXml, string elementName, string value)
        {
            var parametersNode = persistXml.SelectSingleNode(ParametersXPath);
            if (parametersNode != null)
            {
                var destinationRootNode = parametersNode.SelectSingleNode(elementName);
                if (destinationRootNode != null)
                    destinationRootNode.InnerText = value;
            }
        }

        private static string ReadString(XmlDocument persistXml, string elementName)
        {
            var parametersNode = persistXml.SelectSingleNode(ParametersXPath);
            if (parametersNode != null)
            {
                var destinationRootNode = parametersNode.SelectSingleNode(elementName);
                if (destinationRootNode != null)
                    return destinationRootNode.InnerText;
            }

            return null;
        }

        private static void WriteBoolean(XmlDocument persistXml, string elementName, bool value)
        {
            var parametersNode = persistXml.SelectSingleNode(ParametersXPath);
            if (parametersNode != null)
            {
                var elementNode = parametersNode.SelectSingleNode(elementName);
                if (elementNode != null)
                    elementNode.InnerText = Convert.ToString(value);
            }
        }

        private static bool ReadBoolean(XmlDocument persistXml, string elementName, bool defaultValue)
        {
            var parametersNode = persistXml.SelectSingleNode(ParametersXPath);
            if (parametersNode != null)
            {
                var elementNode = parametersNode.SelectSingleNode(elementName);
                if (elementNode != null)
                {
                    bool result;
                    if (bool.TryParse(elementNode.InnerText, out result))
                        return result;
                }
            }

            return defaultValue;
        }
    }
}